package org.dreamwork.jasmine2.web.controls;

import org.dreamwork.jasmine2.util.WebControlCollection;
import org.dreamwork.jasmine2.util.StringConverter;
import org.dreamwork.jasmine2.web.IWebContainer;
import org.dreamwork.jasmine2.web.IWebControl;
import org.dreamwork.jasmine2.events.EventException;
import org.dreamwork.jasmine2.events.IDataBindListener;
import org.dreamwork.jasmine2.engine.IBindable;
import org.dreamwork.jasmine2.engine.HttpContext;
import org.dreamwork.util.ICollection;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.Iterator;

/**
 * Created by IntelliJ IDEA.
 * User: seth
 * Date: 2009-1-4
 * Time: 17:24:53
 */
public class WebContainer extends WebControl implements IWebContainer {
    protected WebControlCollection childControls = new WebControlCollection ();

    protected boolean childControlCreated = false;

    // life circle
    public void init () {
        if (context == null)
            context = HttpContext.current ();
        if (page == null)
            page = context.getPage ();
//        }
        for (int i = 0; i < childControls.count (); i++) {
            IWebControl control = childControls.getControl (i);
            if (!(control instanceof UserControl))
                control.setPage (page);
            control.init ();
            if (control instanceof WebControl)
                ((WebControl) control).setHttpContext (context);
        }
        super.init ();
    }

    @Override
    public void firePreRenderEvents () throws EventException {
        super.firePreRenderEvents ();

        for (int i = 0; i < childControls.count (); i ++) {
            IWebControl c = childControls.getControl (i);
            if (c instanceof WebControl)
                ((WebControl) c).firePreRenderEvents ();
        }
    }

    public void fireDataBindEvents () throws EventException {
        IDataBindListener[] ssls = getDataBindEvents ();
        for (IDataBindListener ssl : ssls) {
            ssl.onDataBind (this);
        }

        try {
            for (int i = 0; i < childControls.count (); i++) {
                IWebControl c = childControls.getControl (i);
                if (c instanceof UserControl) { }
                else if (c instanceof WebControl) ((WebControl) c).dataBind ();
                else if (c instanceof IBindable) ((IBindable) c).dataBind ();
            }
        } catch (Throwable t) {
            throw new EventException (t);
        }
    }

    public void render (PrintWriter writer) throws IOException, EventException {
        if (!visible) return;
        super.render (writer);
//        int count = getChildControls ().count ();
        for (int i = 0; i < childControls.count (); i++) {
            IWebControl control = childControls.getControl (i);
            control.render (writer);
        }
        endTag (writer);
    }

    public void dispose () throws Throwable {
        for (int i = 0; i < childControls.count (); i++) {
            IWebControl control = childControls.getControl (i);
            control.dispose ();
        }
        childControls.clear ();
    }

    protected void checkControl (IWebControl control) {
        if (parent != null) {
            if (parent == control) throw new IllegalStateException ("Can't add control cxxxxxxx");
            if (parent.getParent () != null) ((WebContainer) parent).checkControl (control);
        }
    }

    public void addControl (IWebControl control) {
        checkControl (control);

        if (page == null) {
            context = HttpContext.current ();
            page = context.getPage ();
        }
        String id = control.getId ();
        if (id == null) {
            id = "_auto_control_" + StringConverter.generateUUID ();
            control.setId (id);
        }
        childControls.add (id, control);
        if (!(control instanceof UserControl) && control.getPage () != page) {
            control.setPage (page);
        }
        if (isInited ()) control.init ();
        control.setParent (this);
    }

    public IWebControl getControl (String name) {
        return childControls.getControl (name);
    }

    public IWebControl getControl (int index) {
        return childControls.getControl (index);
    }

    public ICollection getChildControls () {
        return childControls;
    }

    public boolean isChildControlsCreated () {
        return childControlCreated;
    }

    public void createChildControls () {
        for (int i = 0; i < childControls.count (); i++) {
            IWebControl c = childControls.getControl (i);
            if (c instanceof IWebContainer) {
                IWebContainer wc = (IWebContainer) c;
                if (!wc.isChildControlsCreated ())
                    ((IWebContainer) c).createChildControls ();
            }
        }

        childControlCreated = true;
    }

    protected void beginTag (PrintWriter writer) throws IOException {
        if (htmlTagName == null || htmlTagName.trim ().length () == 0) return;
        writer.print ("<" + htmlTagName);

        if (attrs.containsKey ("id")) attrs.remove ("id");
        String id = getClientId ();
        if (StringConverter.isEmpty (id) || id.startsWith ("_auto_"))
            id = getAttribute ("clientid");
        attrs.remove ("clientid");

        if (!StringConverter.isEmpty (id) && !id.startsWith ("_auto_"))
            writer.printf (" id=\"%s\"", id);
        for (Object o : attrs.keySet ()) {
            String attrName = (String) o;
            if (isIgnoredAttribute (attrName)) continue;
            String value = attrs.getProperty (attrName);
            writer.printf (" %s=\"%s\"", attrName, value);
        }

        StringBuffer buffer = new StringBuffer ();
        for (Iterator iter = getStyleNames (); iter.hasNext ();) {
            String name = (String) iter.next ();
            String value = getStyle (name);
            if (buffer.length () > 0) buffer.append (';');
            buffer.append (name).append (':').append (value);
        }
        if (buffer.length () > 0)
            writer.printf (" style=\"%s\"", buffer);
        writer.print (">");
    }

    protected void endTag (PrintWriter writer) {
        if (htmlTagName == null || htmlTagName.trim ().length () == 0) return;
//        if (childControls.count () == 0) return;
        writer.printf ("</%s>%n", htmlTagName);
    }
}